﻿//*****************************************************************************
//
//  Silver Games - Checkers
//  Copyright © 2009 Randi Relander
//      <rjrelander@users.sourceforge.net>
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
//*****************************************************************************

using System;
using System.Collections.Generic;

namespace Checkers.Common
{
    public enum CheckerColor
    {
        Red,
        Black
    };

    public class CheckerList : List<Checker>
    {
    }

    public class Checker
    {
        public class MoveEventArgs : EventArgs
        {
            public Tile Tile1 { get; set; }
            public Tile Tile2 { get; set; }
        }

        public delegate void MoveEventHandler(object sender, MoveEventArgs e);

        public Checker(int index, CheckerColor color)
        {
            mIndex = index;

            mColor = color;
        }

        int mIndex;

        CheckerColor mColor;

        public event MoveEventHandler MoveEvent;
        public event EventHandler MoveCompleteEvent;
        public event EventHandler AddCrownEvent;
        public event EventHandler RemoveCrownEvent;

        public int Index { get { return mIndex; } }

        public CheckerColor Color { get { return mColor; } }

        public Tile StartTile { get; set; }

        bool mIsKing;

        public bool IsKing
        {
            get { return mIsKing; }

            set
            {
                if (value != mIsKing)
                {
                    mIsKing = value;

                    if (IsKing)
                    {
                        if (AddCrownEvent != null)
                        {
                            AddCrownEvent(this, null);
                        }
                    }
                    else
                    {
                        if (RemoveCrownEvent != null)
                        {
                            RemoveCrownEvent(this, null);
                        }
                    }
                }
            }
        }

        public Tile Tile { get; set; }

        public void MoveTo(Tile tile)
        {
            if (Tile != null) Tile.Checker = null;

            Tile tile1 = Tile;

            Tile = tile;

            Tile tile2 = tile;

            if (Tile != null) Tile.Checker = this;

            if (MoveEvent != null)
            {
                MoveEventArgs eventArgs = new MoveEventArgs();

                eventArgs.Tile1 = tile1;
                eventArgs.Tile2 = tile2;

                MoveEvent(this, eventArgs);
            }
        }

        public void OnMoveComplete()
        {
            if (MoveCompleteEvent != null)
            {
                MoveCompleteEvent(this, null);
            }
        }

        public void Capture()
        {
            MoveTo(null);
        }

        public Tile GetNextTile(Direction direction, int distance)
        {
            if (Tile == null) return null;

            return Tile.GetNextTile(Color, direction, distance);
        }

        public bool IsGoingToBeCrowned()
        {
            if (IsKing) return false;

            if ((Tile.Y == 7) && (Color == CheckerColor.Red))
            {
                return true;
            }

            if ((Tile.Y == 0) && (Color == CheckerColor.Black))
            {
                return true;
            }

            return false;
        }

        public bool CanMove(Direction direction)
        {
            bool canMove = false;

            Tile tile1 = GetNextTile(direction, 1);

            if (tile1 != null)
            {
                if (tile1.Checker == null)
                {
                    canMove = true;
                }
            }

            return canMove;
        }

        public bool CanJump(Direction direction)
        {
            bool canJump = false;

            Tile tile1 = GetNextTile(direction, 1);
            Tile tile2 = GetNextTile(direction, 2);

            if ((tile1 != null) && (tile2 != null))
            {
                if ((tile1.Checker != null) && (tile2.Checker == null))
                {
                    if (tile1.Checker.Color != Color)
                    {
                        canJump = true;
                    }
                }
            }

            return canJump;
        }

        public bool CanMove()
        {
            if (CanMove(Direction.NorthEast)) return true;
            if (CanMove(Direction.NorthWest)) return true;

            if (IsKing)
            {
                if (CanMove(Direction.SouthEast)) return true;
                if (CanMove(Direction.SouthWest)) return true;
            }

            return false;
        }

        public bool CanJump()
        {
            if (CanJump(Direction.NorthEast)) return true;
            if (CanJump(Direction.NorthWest)) return true;

            if (IsKing)
            {
                if (CanJump(Direction.SouthEast)) return true;
                if (CanJump(Direction.SouthWest)) return true;
            }

            return false;
        }

        public MoveList GetMoveList()
        {
            MoveList moveList = new MoveList();

            if (CanMove(Direction.NorthEast)) moveList.AddMove(this, Direction.NorthEast);
            if (CanMove(Direction.NorthWest)) moveList.AddMove(this, Direction.NorthWest);

            if (IsKing)
            {
                if (CanMove(Direction.SouthEast)) moveList.AddMove(this, Direction.SouthEast);
                if (CanMove(Direction.SouthWest)) moveList.AddMove(this, Direction.SouthWest);
            }

            return moveList;
        }

        public MoveList GetJumpList()
        {
            MoveList jumpList = new MoveList();

            if (CanJump(Direction.NorthEast)) jumpList.AddJump(this, Direction.NorthEast);
            if (CanJump(Direction.NorthWest)) jumpList.AddJump(this, Direction.NorthWest);

            if (IsKing)
            {
                if (CanJump(Direction.SouthEast)) jumpList.AddJump(this, Direction.SouthEast);
                if (CanJump(Direction.SouthWest)) jumpList.AddJump(this, Direction.SouthWest);
            }

            return jumpList;
        }
    }
}
